package com.py.framework.controller;

import com.py.framework.common.Constants;
import com.py.framework.common.controller.SystemController;
import com.py.framework.core.common.Page;
import com.py.framework.core.exception.ServiceException;
import com.py.framework.core.log.ExceptionLogger;
import com.py.framework.core.rest.support.RestServiceResult;
import com.py.framework.entity.TaskEntity;
import com.py.framework.service.TaskService;
import org.apache.commons.lang.StringUtils;
import org.quartz.CronExpression;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.text.ParseException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 任务管理Controller
 *
 * @author Leegern
 * @date 2018年4月22日
 */
@RestController
@RequestMapping("/task")
public class TaskController extends SystemController {

    @Autowired
    private TaskService taskService;


    /**
     * @api {post} /task/addTaskInfo.json 添加任务实体
     * @apiName addTaskInfo
     * @apiVersion 0.0.1
     * @apiGroup 任务管理
     * @apiParam {TaskEntity}  entity 任务实体
     * @apiParam {String} taskName 任务名称
     * @apiParam {String} taskDesc 任务描述
     * @apiParam {String} taskUrl 任务调用地址
     * @apiParam {String} menuId 所属系统ID
     * @apiParam {String} cronExp CRON表达式
     * @apiParam {String} taskStatus 任务状态，1：开启，2：停用
     * @apiParamExample {json} 请求参数示例
     * {"taskName":"工作流反馈定时任务","taskDesc":"工作流反馈定时任务","taskUrl":"/workflow/processHandleResult.do","menuId":17,"cronExp":"0 * * * * ?"}
     * @apiSuccess {String} code 状态码:0 成功 -1 失败
     * @apiSuccess {String} msg 错误信息
     * @apiSuccess {int} count 结果集数据量
     * @apiSuccess {String} data 结果集
     * @apiSuccessExample {json} 成功返回结果
     * {"code":0,"msg":null,"count":0,"data":null}
     */
    @RequestMapping(value = "/addTaskInfo", method = RequestMethod.POST)
    public RestServiceResult<Object> addTaskInfo(@RequestBody TaskEntity entity) {
        RestServiceResult<Object> result = super.getSuccessRestServiceResult();
        if (null != entity) {
            try {
                taskService.addTaskInfo(entity);
            } catch (Exception e) {
                result = super.getFailedRestServiceResult("添加失败！");
                ExceptionLogger.error(e);
            }
        }
        return result;
    }


    /**
     * @api {post} /task/addTaskInfo.json 添加任务实体
     * @apiName addTaskInfo
     * @apiVersion 0.0.1
     * @apiGroup 任务管理
     * @apiParam {TaskEntity}  entity 任务实体
     * @apiParam {String} taskName 任务名称
     * @apiParam {String} taskDesc 任务描述
     * @apiParam {String} taskUrl 任务调用地址
     * @apiParam {String} menuId 所属系统ID
     * @apiParam {String} cronExp CRON表达式
     * @apiParam {String} taskStatus 任务状态，1：开启，2：停用
     * @apiParamExample {json} 请求参数示例
     * {"taskName":"工作流反馈定时任务","taskDesc":"工作流反馈定时任务","taskUrl":"/workflow/processHandleResult.do","menuId":17,"cronExp":"0 * * * * ?"}
     * @apiSuccess {String} code 状态码:0 成功 -1 失败
     * @apiSuccess {String} msg 错误信息
     * @apiSuccess {int} count 结果集数据量
     * @apiSuccess {String} data 结果集
     * @apiSuccessExample {json} 成功返回结果
     * {"code":0,"msg":null,"count":0,"data":null}
     */
    @RequestMapping(value = "/addTaskInfoForXypj.do", method = RequestMethod.POST)
    public RestServiceResult<String> addTaskInfoForXypj(String taskName, String menuId, String taskDesc, String taskUrl, String cronExp) {
        RestServiceResult<String> result = super.getSuccessRestServiceResult();
        TaskEntity entity = new TaskEntity();
        entity.setMenuId(Long.valueOf(menuId));
        entity.setCronExp(cronExp);
        entity.setTaskDesc(taskDesc);
        entity.setTaskName(taskName);
        entity.setTaskUrl(taskUrl);
        if (null != entity) {
            try {
                taskService.addTaskInfoForXypj(entity);
            } catch (Exception e) {
                result = super.getFailedRestServiceResult("添加失败！");
                ExceptionLogger.error(e);
            }
        }
        return result;
    }

    /**
     * @api {post} /task/addTaskInfo.json 添加任务实体
     * @apiName addTaskInfo
     * @apiVersion 0.0.1
     * @apiGroup 任务管理
     * @apiParam {TaskEntity}  entity 任务实体
     * @apiParam {String} taskName 任务名称
     * @apiParam {String} taskDesc 任务描述
     * @apiParam {String} taskUrl 任务调用地址
     * @apiParam {String} menuId 所属系统ID
     * @apiParam {String} cronExp CRON表达式
     * @apiParam {String} taskStatus 任务状态，1：开启，2：停用
     * @apiParamExample {json} 请求参数示例
     * {"taskName":"工作流反馈定时任务","taskDesc":"工作流反馈定时任务","taskUrl":"/workflow/processHandleResult.do","menuId":17,"cronExp":"0 * * * * ?"}
     * @apiSuccess {String} code 状态码:0 成功 -1 失败
     * @apiSuccess {String} msg 错误信息
     * @apiSuccess {int} count 结果集数据量
     * @apiSuccess {String} data 结果集
     * @apiSuccessExample {json} 成功返回结果
     * {"code":0,"msg":null,"count":0,"data":null}
     */
    @RequestMapping(value = "/updateTaskStatusForXypj.do", method = RequestMethod.POST)
    public RestServiceResult<String> updateTaskStatusForXypj(String status, long menuId, String taskUrl) {
        RestServiceResult<String> result = super.getSuccessRestServiceResult();
        try {
            taskService.updateTaskStatusForXypj(status, menuId, taskUrl);
        } catch (Exception e) {
            result = super.getFailedRestServiceResult("添加失败！");
            ExceptionLogger.error(e);
        }
        return result;
    }

    /**
     * @api {post} /task/queryTaskListForPage.json 分页查询任务列表
     * @apiName queryTaskListForPage
     * @apiVersion 0.0.1
     * @apiGroup 任务管理
     * @apiParam {int}  page 当前页码
     * @apiParam {int}  limit 每页条数
     * @apiParam {String}  taskName 任务名称
     * @apiParam {int}  taskStatus 任务状态, 1：开启，2：停用
     * @apiParamExample {json} 请求参数示例
     * {}
     * @apiSuccess {String} code 状态码:0 成功 -1 失败
     * @apiSuccess {String} msg 错误信息
     * @apiSuccess {int} count 结果集数据量
     * @apiSuccess {String} data 结果集
     * @apiSuccessExample {json} 成功返回结果
     * {"code":0,"msg":null,"count":1,"data":[{"id":11,"createTime":1530870365000,"updateTime":1531367044000,"delFlag":1,"taskName":"工作流反馈定时任务","taskDesc":"工作流反馈定时任务","taskUrl":"/workflow/processHandleResult.do","menuId":17,"cronExp":"0 *2 * * * ?","taskStatus":1,"updFlag":0,"sysName":"数据资源目录子系统","sysAddr":"http://10.10.136.57:8086/credit-data-platform"}]}
     */
    @RequestMapping(value = "/queryTaskListForPage", method = RequestMethod.POST)
    public RestServiceResult<List<TaskEntity>> queryTaskListForPage(int page, int limit, String taskName,
                                                                    @RequestParam(value = "taskStatus", required = false, defaultValue = "0") int taskStatus) {
        Map<String, Object> params = new HashMap<>();
        Page pager = super.getPage(page, limit);
        params.put("page", pager);
        params.put("taskName", taskName);
        params.put("taskStatus", taskStatus);
        List<TaskEntity> datas = taskService.queryTaskListForPage(params);
        return super.getPageSuccessRestServiceResult(pager.getTotalCount(), datas);
    }

    /**
     * @api {post} /task/findOneTask.json 根据任务Id获取任务信息
     * @apiName findOneTask
     * @apiVersion 0.0.1
     * @apiGroup 任务管理
     * @apiParam {long}  id 任务Id
     * @apiParamExample {json} 请求参数示例
     * {}
     * @apiSuccess {String} code 状态码:0 成功 -1 失败
     * @apiSuccess {String} msg 错误信息
     * @apiSuccess {int} count 结果集数据量
     * @apiSuccess {String} data 结果集
     * @apiSuccessExample {json} 成功返回结果
     * {"code":0,"msg":null,"count":1,"data":{"id":11,"createTime":1530870365000,"updateTime":1531367044000,"delFlag":1,"taskName":"工作流反馈定时任务","taskDesc":"工作流反馈定时任务","taskUrl":"/workflow/processHandleResult.do","menuId":17,"cronExp":"0 *2 * * * ?","taskStatus":1,"updFlag":0,"sysName":"数据资源目录子系统","sysAddr":"http://10.10.136.57:8086/credit-data-platform"}}
     */
    @RequestMapping(value = "/findOneTask", method = RequestMethod.POST)
    public RestServiceResult<TaskEntity> findOneTask(long id) {
        TaskEntity data = null;
        if (id > Constants.NUMBER_ZERO) {
            data = taskService.findOneTask(id);
        }
        return super.getSuccessRestServiceResult(data);
    }

    /**
     * @api {post} /task/updateTaskInfo.json 更新任务信息
     * @apiName updateTaskInfo
     * @apiVersion 0.0.1
     * @apiGroup 任务管理
     * @apiParam {TaskEntity}  entity 任务实体
     * @apiParam {String} taskName 任务名称
     * @apiParam {String} taskDesc 任务描述
     * @apiParam {String} taskUrl 任务调用地址
     * @apiParam {String} menuId 所属系统ID
     * @apiParam {String} cronExp CRON表达式
     * @apiParam {String} taskStatus 任务状态，1：开启，2：停用
     * @apiParamExample {json} 请求参数示例
     * {"taskName":"工作流反馈定时任务","taskDesc":"工作流反馈定时任务","taskUrl":"/workflow/processHandleResult.do","menuId":17,"cronExp":"0 * * * * ?"}
     * @apiSuccess {String} code 状态码:0 成功 -1 失败
     * @apiSuccess {String} msg 错误信息
     * @apiSuccess {int} count 结果集数据量
     * @apiSuccess {String} data 结果集
     * @apiSuccessExample {json} 成功返回结果
     * {"code":0,"msg":null,"count":0,"data":null}
     */
    @RequestMapping(value = "/updateTaskInfo", method = RequestMethod.POST)
    public RestServiceResult<Object> updateTaskInfo(@RequestBody TaskEntity entity) {
        RestServiceResult<Object> result = super.getSuccessRestServiceResult();
        if (null != entity) {
            try {
                taskService.updateTaskInfo(entity);
            } catch (Exception e) {
                result = super.getFailedRestServiceResult("更新失败！");
                ExceptionLogger.error(e);
            }
        }
        return result;
    }

    /**
     * @api {post} /task/updateTaskStatus.json 更新任务信息
     * @apiName updateTaskStatus
     * @apiVersion 0.0.1
     * @apiGroup 任务管理
     * @apiParam {long}  id 任务Id
     * @apiParam {int}  taskStatus 任务状态
     * @apiParamExample {json} 请求参数示例
     * {}
     * @apiSuccess {String} code 状态码:0 成功 -1 失败
     * @apiSuccess {String} msg 错误信息
     * @apiSuccess {int} count 结果集数据量
     * @apiSuccess {String} data 结果集
     * @apiSuccessExample {json} 成功返回结果
     * {"code":0,"msg":null,"count":0,"data":null}
     */
    @RequestMapping(value = "/updateTaskStatus", method = RequestMethod.POST)
    public RestServiceResult<Object> updateTaskStatus(long id, int taskStatus) {
        RestServiceResult<Object> result = super.getSuccessRestServiceResult();
        if (id > Constants.NUMBER_ZERO && taskStatus > Constants.NUMBER_ZERO) {
            try {
                taskService.updateTaskStatus(id, taskStatus);
            } catch (Exception e) {
                result = super.getFailedRestServiceResult("操作失败！");
                ExceptionLogger.error(e);
            }
        }
        return result;
    }

    /**
     * @api {post} /task/batchDelTasks.json 批量删除任务
     * @apiName batchDelTasks
     * @apiVersion 0.0.1
     * @apiGroup 任务管理
     * @apiParam {String}  ids 任务Id集合
     * @apiParamExample {json} 请求参数示例
     * {}
     * @apiSuccess {String} code 状态码:0 成功 -1 失败
     * @apiSuccess {String} msg 错误信息
     * @apiSuccess {int} count 结果集数据量
     * @apiSuccess {String} data 结果集
     * @apiSuccessExample {json} 成功返回结果
     * {"code":0,"msg":null,"count":0,"data":null}
     */
    @RequestMapping(value = "/batchDelTasks", method = RequestMethod.POST)
    public RestServiceResult<Object> batchDelTasks(String ids) {
        RestServiceResult<Object> result = super.getSuccessRestServiceResult();
        if (StringUtils.isNotBlank(ids)) {
            try {
                taskService.batchDelTasks(super.convert2Long(ids));
            } catch (ServiceException e) {
                result = super.getFailedRestServiceResult(e.getMsg());
            } catch (Exception e) {
                result = super.getFailedRestServiceResult("删除失败！");
                ExceptionLogger.error(e);
            }
        }
        return result;
    }

    /**
     * 功能描述:Cron表达式反解析
     *
     * @param cron cron表达式
     * @return 最近五次执行时间
     * @author YaoS
     * @date 19/3/28 16:14
     */
    @RequestMapping(value = "/cronExpParser", method = RequestMethod.POST)
    public RestServiceResult<List> cronExpParser(String cron) {
        RestServiceResult<List> result;
        List list = new ArrayList(5);
        Date curTime = new Date();
        try {
            CronExpression expression = new CronExpression(cron);
            for (int i = 1; i < 6; i++) {
                curTime = expression.getNextValidTimeAfter(curTime);
                list.add("第" + i + "次:" + dateUtil(curTime));
            }
            result = super.getSuccessRestServiceResult(list);
        } catch (ParseException e) {
            result = super.getFailedRestServiceResult("无法解析Cron,请检查表达式！");
        }
        return result;
    }

    private static String dateUtil(Date date) {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
        return localDateTime.format(dtf);
    }

    public static class Conditions {
        private int page;
        private int limit;
        private String taskName;
        private int taskStatus;

        /**
         * @return the page
         */
        public int getPage() {
            return page;
        }

        /**
         * @param page the page to set
         */
        public void setPage(int page) {
            this.page = page;
        }

        /**
         * @return the limit
         */
        public int getLimit() {
            return limit;
        }

        /**
         * @param limit the limit to set
         */
        public void setLimit(int limit) {
            this.limit = limit;
        }

        /**
         * @return the taskName
         */
        public String getTaskName() {
            return taskName;
        }

        /**
         * @param taskName the taskName to set
         */
        public void setTaskName(String taskName) {
            this.taskName = taskName;
        }

        /**
         * @return the taskStatus
         */
        public int getTaskStatus() {
            return taskStatus;
        }

        /**
         * @param taskStatus the taskStatus to set
         */
        public void setTaskStatus(int taskStatus) {
            this.taskStatus = taskStatus;
        }
    }
}